#ifndef AVALON_CODEDREADER_HPP
#define AVALON_CODEDREADER_HPP
#include "Avalon/Base/Handle.hpp"
#include "Avalon/Codecs/Codecs.hpp"
#include "Avalon/IO/Buffer.hpp"
#include "Avalon/IO/Reader.hpp"

namespace Avalon {
namespace Codecs {

  /*! \class CodedReader
   *  \brief Reads coded data using a Decoder.
   */
  class CodedReader : public IO::Reader {
    public:

      //! Constructs a CodedReader.
      /*!
        \param source The source to read from.
        \param decoder The Decoder to use.
      */
      CodedReader(Carry<IO::Reader> source, Decoder* decoder);

      virtual ~CodedReader();

      virtual void Read(void* destination, int size,
        Out<Threading::Async<int> > sizeRead);

      virtual void Read(IO::Buffer* destination, int size,
        Out<Threading::Async<int> > sizeRead);

      using IO::Reader::Read;

    private:
      Handle<IO::Reader> m_source;
      boost::scoped_ptr<Decoder> m_decoder;
      boost::scoped_ptr<IO::BufferReader> m_destinationReader;
      IO::Buffer m_sourceBuffer;
      int m_sizeRemaining;
      IO::Buffer* m_buffer;
      void* m_destination;
      int m_size;
      Threading::Async<int> m_bufferRead;
      Threading::Async<int> m_dataRead;
      Threading::Async<int>* m_result;

      void OnBufferRead();
      void OnDataRead();
  };
}
}

#endif // AVALON_CODEDREADER_HPP
